/* COPYRIGHT_CHUNFENG */
#include "cf_string.h"
#include "cf_std.h"

#ifdef LACK_MEMORY
#define CF_STRING_BUFFER_NEW_MIN_SIZE 0
#else
#define CF_STRING_BUFFER_NEW_MIN_SIZE 250
#endif

int CFStringInitLen(CFString* this, const char* start, unsigned int len)
{
    this->alloc_size = len + 1 + CF_STRING_BUFFER_NEW_MIN_SIZE;    
    this->str = malloc(this->alloc_size);
    strncpy(this->str, start, len);
    this->str[len]=0;
    this->len = len;
    return 0;
}

int CFStringInit(CFString* this, const char* str)
{
    return CFStringInitLen(this, str, strlen(str));
}

CFString* cf_string_new_len(const char* start, unsigned int len)
{
    CFString *this;
    this = (CFString*)malloc(sizeof(CFString));
    CFStringInitLen(this, start, len);
    return this;
}

CFString* cf_string_new(const char* str)
{
    unsigned int len = strlen(str);
    return cf_string_new_len(str, len);
}

CFString* cf_string_new_start_end(const char* start, const char* end)
{
    unsigned int len = end - start + 1;
    return cf_string_new_len(start, len);
}

int CFStringExit(CFString* this)
{
    free(this->str);
    return 0;
}

void cf_string_free(CFString* this)
{
    CFStringExit(this);
    free(this);
}

CFString* cf_string_safe_cp_n(CFString* this, const char* source, unsigned int source_len)
{
    if(this->alloc_size < source_len+1){
        this->str = realloc(this->str, source_len+1);
        this->alloc_size = source_len + 1;
    }
    strncpy(this->str, source, source_len);
    this->str[source_len] = '\0';
    this->len = strlen(this->str);
    return this;
}

CFString* cf_string_safe_cp(CFString* this, const char* source)
{
    unsigned source_len = strlen(source);
    if(this->alloc_size < source_len+1){
        this->str = realloc(this->str, source_len+1);
        this->alloc_size = source_len + 1;
    }
    strncpy(this->str, source, source_len);
    this->str[source_len] = '\0';
    this->len = source_len;
    return this;
}

CFString* cf_string_safe_cat_n(CFString* this, const char* source, unsigned int source_len)
{
    unsigned int needed_size = this->len + source_len+1;
    if(this->alloc_size < needed_size){
        this->str = realloc(this->str, needed_size);
        this->alloc_size = needed_size;
    }
    strncat(this->str + this->len, source, source_len);
    this->len = needed_size - 1;
    return this;
}

CFString* cf_string_safe_cat(CFString* this, const char* source)
{
    unsigned int source_len = strlen(source);
    return cf_string_safe_cat_n(this, source, source_len);
}
/*
int main(int argc, char** argv)
{
    CFString* this = cf_string_new("1234567890");
    printf("str=%s\nlen=%u\nalloc_size=%u\n", 
        cf_string_get_str(this), 
        cf_string_get_len(this), 
        cf_string_get_size(this)
    );
    cf_string_safe_cp(this, "abcdefghijklmnopqrstuvwxyz");
    cf_string_safe_cat(this, "1234567890");
    printf("str=%s\nlen=%u\nalloc_size=%u\n", 
        cf_string_get_str(this), 
        cf_string_get_len(this), 
        cf_string_get_size(this)
    );    
    cf_string_free(this);
    return 0;
}
*/
